package main.java.model;
import java.util.Observable;
import java.util.Random;

public class Doors extends Observable {
    
    //static final variables to sleep time
    private static final int DEFAULT_SLEEP = 1600;
    
    //static final variables to change positions id easier
    private static final int CLOSED_ID = 0;
    private static final int MANEUVERING_ID = 1;
    private static final int OPENED_ID = 2;
    private static final int FAILURE_ID = 3;
    
    //static final variables failure rate
    private static final float FAILURE_RATE = (float) 0.05;
    
    private int position, sleepUp, sleepDown;;
    
    /**
     * Constructor Door
     */
    public Doors() {
        this.position = CLOSED_ID;
        this.sleepUp = DEFAULT_SLEEP;
        this.sleepDown = DEFAULT_SLEEP;
    }
    
    /**
     * Construction Doors
     * @param sleepUp : Time configuration depending on which door to go up
     * @param sleepDown : Time configuration depending on which door to go down
     */
    public Doors(int sleepUp, int sleepDown) {
        this.position = CLOSED_ID;
        this.sleepUp = sleepUp;
        this.sleepDown = sleepDown;
    }
    
    /**
     * Doors' action depending on the change that happened
     * @param position : the change
     */
    public void action(String position) {
        switch (position) {
            case "High":
                try {
                    //Sleep
                    Thread.sleep(sleepUp); 
                } catch (InterruptedException e) {
                }
                //Set to closed
                setPosition(CLOSED_ID); 
                break;
            case "InProgress":
                //Set to maneuvering
                setPosition(MANEUVERING_ID); 
                break;
            case "Down":
                try {
                    //Sleep
                    Thread.sleep(sleepDown); 
                } catch (InterruptedException e) {
                }
                //Set to opened
                setPosition(OPENED_ID); 
                break;
            case "Maneuvering":
                maneuveringClosed();
                break;
            default:
                break;
        }
    }
    
    /**
     * maneuvering to close position
     */
    public void maneuveringClosed() {
        //Set to maneuvering 
        setPosition(MANEUVERING_ID); 
        try {
            //Sleep
            Thread.sleep(sleepDown); 
        } catch (InterruptedException e) {
        }
        //Set to closed
        setPosition(CLOSED_ID);
    }
    
    /**
     * Return the position in a string
     * @return String : the position in a string
     */
    public String positionToString() {
        switch (position) {
            case CLOSED_ID :
                return "Closed";
            case MANEUVERING_ID :
                return "Maneuvering";
            case OPENED_ID :
                return "Opened";
            case FAILURE_ID :
                return "Failure";
            default :
                return "Default";
        }
    }
    
    /**
     * From the string value of the position
     * Get the number that matches
     * @param positionString : the string
     * @return int : the number
     */
    public int getPositionValue(String positionString) {
        switch (positionString) {
            case "Closed" :
                return CLOSED_ID;
            case "Maneuvering" :
                return MANEUVERING_ID;
            case "Opened" :
                return OPENED_ID;
            case "Failure" :
                return FAILURE_ID;
            default :
                return -1;
        }
    }
    
    /**
     * Set Position and notify the main application
     * @param position : the new position
     */
    public void setPosition(int position) {
        this.position = position;
        
        //If the door is trying to get openned
        if (this.position == OPENED_ID) {
        	//Random value between 0 and 1
	        Random rand = new Random();
	        //Pourcentage of failure
	        if(rand.nextFloat() < FAILURE_RATE) {
	        	this.position = FAILURE_ID;
	        }
        }
        
        //Setting changes
        setChanged(); 
        //Notify
        notifyObservers(positionToString()); 
    }

    public int getPosition() {
        return position;
    }
}
